"""


"""

import os
import logging
import hashlib
from pathlib import Path
from typing import List, Optional, Union
import shutil

def setup_logging(log_level: str = 'INFO', log_file: Optional[str] = None):
    """"""
    logging.basicConfig(
        level=getattr(logging, log_level.upper()),
        format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
        handlers=[
            logging.StreamHandler(),
            logging.FileHandler(log_file) if log_file else logging.NullHandler()
        ]
    )

def format_file_size(size_bytes: int) -> str:
    """"""
    if size_bytes == 0:
        return "0B"
    
    size_names = ["B", "KB", "MB", "GB", "TB"]
    i = 0
    while size_bytes >= 1024 and i < len(size_names) - 1:
        size_bytes /= 1024.0
        i += 1
    
    return f"{size_bytes:.1f}{size_names[i]}"

def format_duration(seconds: float) -> str:
    """"""
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    seconds = int(seconds % 60)
    
    if hours > 0:
        return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
    else:
        return f"{minutes:02d}:{seconds:02d}"

def get_file_hash(file_path: str, algorithm: str = 'md5') -> str:
    """"""
    hash_func = hashlib.new(algorithm)
    
    with open(file_path, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_func.update(chunk)
    
    return hash_func.hexdigest()

def ensure_dir(directory: Union[str, Path]):
    """"""
    Path(directory).mkdir(parents=True, exist_ok=True)

def clean_filename(filename: str) -> str:
    """"""
    invalid_chars = '<>:"/\\|?*'
    for char in invalid_chars:
        filename = filename.replace(char, '_')
    return filename.strip()

def get_available_filename(file_path: str) -> str:
    """"""
    path = Path(file_path)
    if not path.exists():
        return file_path
    
    stem = path.stem
    suffix = path.suffix
    parent = path.parent
    counter = 1
    
    while True:
        new_name = f"{stem}_{counter}{suffix}"
        new_path = parent / new_name
        if not new_path.exists():
            return str(new_path)
        counter += 1

def copy_file_with_progress(src: str, dst: str, callback=None):
    """"""
    src_path = Path(src)
    dst_path = Path(dst)
    
    # 
    dst_path.parent.mkdir(parents=True, exist_ok=True)
    
    file_size = src_path.stat().st_size
    copied = 0
    
    with open(src_path, 'rb') as fsrc, open(dst_path, 'wb') as fdst:
        while True:
            chunk = fsrc.read(64 * 1024)  # 64KB chunks
            if not chunk:
                break
            fdst.write(chunk)
            copied += len(chunk)
            
            if callback:
                progress = int((copied / file_size) * 100)
                callback(progress)

def validate_file_path(file_path: str, allowed_extensions: List[str] = None) -> bool:
    """"""
    path = Path(file_path)
    
    # 
    if not path.exists():
        return False
    
    # 
    if not path.is_file():
        return False
    
    # 
    if allowed_extensions:
        file_ext = path.suffix.lower()
        return file_ext in [ext.lower() for ext in allowed_extensions]
    
    return True

def get_temp_dir() -> str:
    """"""
    temp_dir = Path.cwd() / "temp"
    temp_dir.mkdir(exist_ok=True)
    return str(temp_dir)

def cleanup_temp_files(temp_dir: str = None):
    """"""
    if temp_dir is None:
        temp_dir = get_temp_dir()
    
    temp_path = Path(temp_dir)
    if temp_path.exists():
        try:
            shutil.rmtree(temp_path)
            temp_path.mkdir(exist_ok=True)
        except Exception as e:
            logging.warning(f": {e}")

def check_disk_space(path: str, required_mb: int) -> bool:
    """"""
    try:
        stat = shutil.disk_usage(path)
        available_mb = stat.free / (1024 * 1024)
        return available_mb >= required_mb
    except Exception:
        return True  # 

def get_system_info() -> dict:
    """"""
    import platform
    import psutil
    
    return {
        'platform': platform.system(),
        'platform_version': platform.version(),
        'architecture': platform.architecture()[0],
        'processor': platform.processor(),
        'python_version': platform.python_version(),
        'cpu_count': os.cpu_count(),
        'memory_total': psutil.virtual_memory().total,
        'memory_available': psutil.virtual_memory().available
    }

class ProgressTracker:
    """"""
    
    def __init__(self, total: int = 100):
        self.total = total
        self.current = 0
        self.callbacks = []
    
    def add_callback(self, callback):
        """"""
        self.callbacks.append(callback)
    
    def update(self, value: int, message: str = ""):
        """"""
        self.current = min(value, self.total)
        for callback in self.callbacks:
            try:
                callback(self.current, message)
            except Exception as e:
                logging.warning(f": {e}")
    
    def increment(self, step: int = 1, message: str = ""):
        """"""
        self.update(self.current + step, message)
    
    def reset(self):
        """"""
        self.current = 0
    
    def is_complete(self) -> bool:
        """"""
        return self.current >= self.total